'abuentity.monkey by Belimoth
Strict
'Import abustage
Import abucomponent
Import abuposition
Import abusize
Import abuvelocity
'Import abuphysics
Import abuphysicsstuntdouble
Import abuspritecomponent
Import aburendercomponents
Import abuschedulecomponent
Import abueventcomponent

'TODO
'	Finalize() methods for all components
'	put the ITweener aspec inside of a component



Class Actor		'Temporary
End



Class EntityBase Extends Actor 
End



Interface IEntity Extends IPosition, ISize, IVelocity, IPhysics, ISprite, IRender, ISchedule, IEventHandler
	Method PositionComponent:IPosition() Property
	Method SizeComponent:ISize() Property
	Method VelocityComponent:IVelocity() Property
	Method PhysicsComponent:IPhysics() Property
	Method SpriteComponent:ISprite() Property
	Method ScheduleComponent:ISchedule() Property
	Method EventComponent:IEventHandler() Property
End

Class AbuEntity Extends EntityBuilder<PositionComponent, SizeComponent, VelocityComponent, PhysicsComponent, SpriteComponent, SpriteRender, ScheduleComponent, NullComponent>
Public
	Method AddTween:Void(name:String, value:Float, duration:Int, flags:Int = TWEEN_DEFAULT)
		Local tweenNew := New AbuTween(Self, name, value, duration, flags)
		Local tweenReplaced := _tweens.Get(name)
		If tweenReplaced <> Null Then tweenReplaced.Destroy()
		_tweens.Set(name, tweenNew)
	End
	
	Method PauseTween:Void(name:String)
		_tweens.Get(name).Pause()
	End
	
	Method ResumeTween:Void(name:String)
		_tweens.Get(name).Resume()
	End
	
	Method RemoveTween:Void(name:String)
		_tweens.Get(name).Destroy()
		_tweens.Remove(name)
	End
	
	Method ClearTweens:Void()
		For Local tween := Eachin _tweens.Values()
			tween.Destroy()
		Next
		_tweens.Clear()
	End
	
	Method OnTweenComplete:Void(name:String)
	
	End
	
	#Rem
	Method AddTimer:Void(name:String, timeTargetRelative:Int = 0)
		Local timerNew := New AbuTimer(timeTargetRelative)
		_timers.Set(name, timerNew)
	End
	
	Method PauseTimer:Void(name:String)
		_timers.Get(name).Pause()
	End
	
	Method ResumeTimer:Void(name:String)
		_timers.Get(name).Resume()
	End
	
	Method RemoveTimer:Void(name:String)
		'_timers.Get(name).Destroy()
		_timers.Remove(name)
	End
	
	Method ClearTimers:Void()
		#Rem
		For Local timer := Eachin _timers.Values()
			timer.Destroy()
		Next
		#End
		_timers.Clear()
	End
	
	Method OnTimerComplete:Void(name:String)
	
	End
	#End
Private
	Field _tweens := New StringMap<AbuTween>
	'Field _timers := New StringMap<AbuTimer>
End

#Rem
Class ShapeEntity Extends EntityBuilder<PositionComponent, SizeComponent, VelocityComponent, PhysicsComponent, NullComponent, ShapeRender, EventComponent>

End
#End

Class EntityBuilder<CPosition, CSize, CVelocity, CPhysics, CSprite, CRender, CSchedule, CEventHandler> Extends EntityBase Implements IEntity

Private
	Field _markedForDeletion:Bool
	
Public	
	Method IntitializeComponents:Void()
		positionComponent.Tie(Self)
		velocityComponent.Tie(Self)
		sizeComponent.Tie(Self)
		physicsComponent.Tie(Self)
		spriteComponent.Tie(Self)
		renderComponent.Tie(Self)
		scheduleComponent.Tie(Self)
		eventComponent.Tie(Self)
	End
	
	Method Finalize:Void()
		positionComponent.Finalize()
		velocityComponent.Finalize()
		sizeComponent.Finalize()
		physicsComponent.Finalize()
		spriteComponent.Finalize()
		renderComponent.Finalize()
		scheduleComponent.Finalize()
		eventComponent.Finalize()
	End
	
	Field positionComponent := New CPosition()'_________________________________________________IPosition component_______________________________________________________
	Method PositionComponent:IPosition() Property												Return positionComponent												End
	Method X:Int() Property																		Return positionComponent.X												End
	Method X:Void(xNew:Int) Property															positionComponent.X = xNew												End
	Method Y:Int() Property																		Return positionComponent.Y												End
	Method Y:Void(yNew:Int) Property															positionComponent.Y = yNew												End
	Method Position:Position() Property															Return positionComponent.Position										End
	Method SetPosition:Void(xNew:Int, yNew:Int)													positionComponent.SetPosition(xNew, yNew)								End
	Method DistanceTo:Float(other:IPosition)													Return positionComponent.DistanceTo(other)								End
	Method AngleTo:Float(other:IPosition)														Return positionComponent.AngleTo(other)									End

	Field velocityComponent := New CVelocity()'_________________________________________________IVelocity component________________________________________________________
	Method VelocityComponent:IVelocity() Property												Return velocityComponent												End
	Method xVelocity:Float() Property															Return velocityComponent.xVelocity										End
	Method xVelocity:Void(xVelocityNew:Float) Property											velocityComponent.xVelocity = xVelocityNew								End
	Method yVelocity:Float() Property															Return velocityComponent.yVelocity										End
	Method yVelocity:Void(yVelocityNew:Float) Property											velocityComponent.yVelocity = yVelocityNew								End
	Method xAcceleration:Float() Property														Return velocityComponent.xAcceleration									End
	Method xAcceleration:Void(xAccelerationNew:Float) Property									velocityComponent.xAcceleration = xAccelerationNew						End
	Method yAcceleration:Float() Property														Return velocityComponent.yAcceleration									End
	Method yAcceleration:Void(yAccelerationNew:Float) Property									velocityComponent.yAcceleration = yAccelerationNew						End
	Method xMaxVelocity:Float() Property														Return velocityComponent.xMaxVelocity									End
	Method yMaxVelocity:Float() Property														Return velocityComponent.yMaxVelocity									End
	Method SetMaxVelocity:Void(xMaxVelocityNew:Float, yMaxVelocityNew:Float)					velocityComponent.SetMaxVelocity(xMaxVelocityNew, yMaxVelocityNew)		End
	Method xDisplacement:Int() Property															Return velocityComponent.xDisplacement									End
	Method yDisplacement:Int() Property															Return velocityComponent.yDisplacement									End

	Field sizeComponent := New CSize()'_________________________________________________________ISize component____________________________________________________________
	Method SizeComponent:ISize() Property														Return sizeComponent													End
	Method Width:Int() Property																	Return sizeComponent.Width												End
	Method Width:Void(widthNew:Int) Property													sizeComponent.Width = widthNew											End
	Method SetWidth:Void(widthNew:Int, align:Int = ALIGN_LEFT)									sizeComponent.SetWidth(widthNew, align)									End
	Method Height:Int() Property																Return sizeComponent.Height												End
	Method Height:Void(heightNew:Int) Property													sizeComponent.Height = heightNew										End
	Method SetHeight:Void(heightNew:Int, align:Int = ALIGN_TOP)									sizeComponent.SetHeight(heightNew, align)								End
	Method SetSize:Void(widthNew:Int, heightNew:Int, align:Int = ALIGN_LEFT|ALIGN_TOP)			sizeComponent.SetSize(widthNew, heightNew, align)						End
	Method GetEdge:Int(direction:Int)															Return sizeComponent.GetEdge(direction)									End
	
	Field physicsComponent := New CPhysics()'___________________________________________________IPhysics component_________________________________________________________
	Method PhysicsComponent:IPhysics() Property													Return physicsComponent													End
	Method Move:Void(x:Int, y:Int)																physicsComponent.Move(x, y)												End
	'Method OnCollision:Void(other:IPhysics)													physicsComponent.OnCollision(other)										End
	'Method HandleTraceResult:Void(result:TraceResult)											physicsComponent.HandleTraceResult(result)								End
	
	Field spriteComponent := New CSprite()'_____________________________________________________ISprite component__________________________________________________________
	Method SpriteComponent:ISprite() Property													Return spriteComponent													End
	Method CurrentAnimation:String() Property													Return spriteComponent.CurrentAnimation									End
	Method NextAnimation:String() Property														Return spriteComponent.NextAnimation									End
	Method LoopCount:Int() Property																Return spriteComponent.LoopCount										End
	Method HandleX:Float() Property																Return spriteComponent.HandleX											End
	Method HandleY:Float() Property																Return spriteComponent.HandleY											End
	Method SetHandle:Void(x:Float, y:Float)														spriteComponent.SetHandle(x, y)											End
	Method AnimationSheet:AbuAnimationSheet() Property											Return spriteComponent.AnimationSheet									End
	Method AnimationSheet:Void(animationSheet:AbuAnimationSheet) Property						spriteComponent.AnimationSheet(animationSheet)							End
	Method SetAnimationSheet:Void(path:String, frameWidth:Int, frameHeight:Int)					spriteComponent.SetAnimationSheet(path, frameWidth, frameHeight)		End
	Method SetRate:Void(rate:Float)																spriteComponent.SetRate(rate)											End	
	Method AddAnimation:Void(name:String, sequence:Int[], frameDuration:Int, loop:Bool = True, flipX:Bool = False, flipY:Bool = False)									'..
		spriteComponent.AddAnimation(name, sequence, frameDuration, loop, flipX, flipY)																					End
	Method AddAnimation:Void(name:String, sequence:Int[], frameDuration:Int[], loop:Bool = True, flipX:Bool = False, flipY:Bool = False)								'..
		spriteComponent.AddAnimation(name, sequence, frameDuration, loop, flipX, flipY)																					End
	Method AddAnimation:Void(name:String, start:Int, sequence:Int[], frameDuration:Int, loop:Bool = True, flipX:Bool = False, flipY:Bool = False)						'..
		spriteComponent.AddAnimation(name, start, sequence, frameDuration, loop, flipX, flipY)																			End
	Method AddAnimation:Void(name:String, start:Int, sequence:Int[], frameDuration:Int[], loop:Bool = True, flipX:Bool = False, flipY:Bool = False)						'..
		spriteComponent.AddAnimation(name, start, sequence, frameDuration, loop, flipX, flipY)																			End
	Method AddAnimation:Void(name:String, subAnimations:String[], loop:Bool = True, flipX:Bool = False, flipY:Bool = False)												'..
		spriteComponent.AddAnimation(name, subAnimations, loop, flipX, flipY)																							End
	Method PlayAnimation:Void(name:String, reset:Bool = True, rate:Float = 1.0)					spriteComponent.PlayAnimation(name, reset, rate)						End
	Method QeueAnimation:Void(name:String, reset:Bool = True, rate:Float = 1.0)					spriteComponent.QeueAnimation(name, reset, rate)						End
	Method PlayNextAnimation:Void()																spriteComponent.PlayNextAnimation();									End
	Method OnAnimationLoop:Void(animation:String) End											'meant to be overriden													'''
	Method OnAnimationEnd:Void(animation:String) End											'meant to be overriden													'''
	Method AddOffset:Void(name:String, offsetX:Int[], offsetY:Int[], cumulative:Bool = False)	spriteComponent.AddOffset(name, offsetX, offsetY, cumulative)			End
	Method AddDisplacement:Void(name:String, displaceX:Int[], displaceY:Int[])					spriteComponent.AddDisplacement(name, displaceX, displaceY)				End
	Method _Displace:Void(x:Int, y:Int) End														'called at the AbuSpriteComponent level									'''
	Method Draw:Void(x:Int, y:Int, rotation:Float = 0, scaleX:Float = 1, scaleY:Float = 1)		spriteComponent.Draw(x, y, rotation, scaleX, scaleY)					End
	
	Field renderComponent := New CRender()'_____________________________________________________IRender component__________________________________________________________
	Method RenderComponent:IRender() Property													Return renderComponent													End
	Method Alpha:Float() Property																Return renderComponent.Alpha											End
	Method Alpha:Void(alpha:Float) Property														renderComponent.Alpha = alpha											End
	Method ZIndex:Int() Property																Return renderComponent.ZIndex											End
	Method ZIndex:Void(zIndex:Int)																renderComponent.ZIndex = zIndex											End
	Method Render:Void()																		renderComponent.Render();												End
	
	Field scheduleComponent := New CSchedule()'_________________________________________________ISchedule component________________________________________________________
	Method ScheduleComponent:ISchedule() Property												Return scheduleComponent												End
	Method AddTween:Void(name:String, value:Float, duration:Int, flags:Int = TWEEN_DEFAULT)		scheduleComponent.AddTween(name, value, duration, flags)				End
	Method PauseTween:Void(name:String)															scheduleComponent.PauseTween(name)										End
	Method ResumeTween:Void(name:String)														scheduleComponent.ResumeTween(name)										End
	Method RemoveTween:Void(name:String)														scheduleComponent.RemoveTween(name)										End
	Method ClearTweens:Void()																	scheduleComponent.ClearTweens();										End
	Method OnTweenComplete:Void(name:String) End												'meant to be overriden													'''
	Method AddTimer:Void(name:String, timeTargetRelative:Int = 0)								scheduleComponent.AddTimer(name, timeTargetRelative)					End
	Method PauseTimer:Void(name:String)															scheduleComponent.PauseTimer(name)										End
	Method ResumeTimer:Void(name:String)														scheduleComponent.ResumeTimer(name)										End
	Method RemoveTimer:Void(name:String)														scheduleComponent.RemoveTimer(name)										End
	Method ClearTimers:Void()																	scheduleComponent.ClearTimers();										End
	Method OnTimerComplete:Void(name:String) End												'meant to be overriden													End
	
	Field eventComponent := New CEventHandler()'________________________________________________IEventHandler component____________________________________________________
	Method EventComponent:IEventHandler() Property												Return eventComponent													End
End